import { createElements, define, itag, Styled } from "../itag/index.js";
import type { SizeFormat } from "../SizeFormat.js";
import { hex } from "../util.js";
import type { IRequestFieldElement } from "./IFieldElement.js";
import type { ListRequestFieldOption } from "./RequestOption.js";
import * as styles from "./styles.js";

const styled = new Styled();

const container = styled.class("container")`
    display: flex;
    flex-wrap: wrap;
    flex-direction: row;
    gap: 0.2em;
    height: 100%;
`;

const content = styled.class("content")`
    display: flex;
    flex-direction: column;
`;

const controls = styled.class("controls")`
    display: flex;
    flex-direction: column;
    height: 100%;
    justify-content: center;
    gap: 0.2em;

    button {
        width: 1.8em;
        height: 1.8em;
        text-align: center;
        cursor: pointer;
        user-select: none;
    }
`;

/**
 * ListGroupElement - 自定义HTML元素，用于处理可变长度的数值列表
 * 显示列表内容以及字节范围信息
 * 实现IGroupElement接口
 */
export class ListRequestFieldElement extends HTMLElement implements IRequestFieldElement {
    /** 开始字节位置 */
    #begin: number = 0;

    /** 组件内DOM元素的引用 */
    readonly #elms = createElements({
        container: "div",
        inputs: "div",
        name: "div",
        range: "div",
        controls: "div",
        addButton: "button",
        removeButton: "button",
    });

    /** 长度字段字节数 */
    #sizeElements: HTMLInputElement[] = [];

    /** 列表中的输入元素 */
    #inputs: HTMLInputElement[] = [];

    /** 组件的Shadow DOM根节点 */
    #sr: ShadowRoot;

    /** 列表中每次增加的步长 */
    #growStep: number = 1;

    /**
     * 初始化组件结构和事件处理器
     */
    constructor() {
        super();
        this.#sr = this.attachShadow({ mode: "open" });
        this.#sr.adoptedStyleSheets.push(styles.sheet, styled.sheet);

        itag`
${this.#sr}
    div .${container}
        ${this.#elms.controls} .${controls}
            ${this.#elms.addButton}  : +
            ${this.#elms.removeButton}  : -
        div .${content}
            ${this.#elms.inputs} .${styles.inputs}
            ${this.#elms.name} .${styles.name}
            ${this.#elms.range} .${styles.range}
`;

        // 添加事件监听器
        this.#elms.addButton.addEventListener("click", () => {
            for (let j = 0; j < this.#growStep; j++) {
                this.#addItem();
            }
        });

        this.#elms.removeButton.addEventListener("click", () => {
            for (let j = 0; j < this.#growStep; j++) {
                this.#removeItem();
            }
        });
    }

    /**
     * 返回列表数据的字节表示
     * 首先是长度字段（使用widthLength指定的字节数），然后是各个数值
     *
     * @returns 表示列表数据的字节数组
     */
    data(): number[] {
        const step = this.#growStep;
        const widthLength = this.#sizeElements.length;
        const result = [];
        const itemCount = this.#inputs.length / step;

        // 存储列表长度，使用指定的字节数（widthLength）
        for (let i = 0; i < widthLength; i++) {
            result.push((itemCount >> (i * 8)) & 0xff);
        }

        // 添加列表中的每个数值
        for (const input of this.#inputs) {
            result.push(parseInt(input.value || "0", 10));
        }

        return result;
    }

    /**
     * 计算该元素的总字节长度
     * 包括长度字段和所有数值
     *
     * @returns 总字节长度
     */
    byteLength(): number {
        return this.#sizeElements.length + this.#inputs.length;
    }

    /**
     * 获取元素的显示名称
     */
    get name(): string {
        return this.#elms.name.textContent ?? "";
    }

    get option(): ListRequestFieldOption {
        return {
            kind: "list",
            name: this.#elms.name.textContent ?? "",
            value: this.data(),
            sizeFormat: this.#sizeElements.length as SizeFormat,
            step: this.#growStep,
        };
    }

    set option(value: ListRequestFieldOption | null) {
        this.#elms.name.textContent = value?.name ?? "";
        this.#growStep = value?.step ?? 1;
        this.#setSizeFormat(value?.sizeFormat);
        this.#setValue(value?.value);
        this.#updateRange();
    }

    /**
     * 设置开始字节位置并更新范围显示
     *
     * @param value 新的开始字节位置
     */
    setBegin(value: number): void {
        if (this.#begin === value) {
            return;
        }
        this.#begin = value;
        this.#updateRange();
    }

    #setSizeFormat(format: SizeFormat | undefined) {
        format = format ?? 0;
        if (this.#sizeElements.length === format) {
            return;
        }
        while (this.#sizeElements.length > format) {
            this.#sizeElements.pop()?.remove();
        }
        while (this.#sizeElements.length < format) {
            const input = document.createElement("input");
            input.classList.add(styles.input, styles.number);
            input.type = "text";
            input.value = "0";
            input.maxLength = 3;
            this.#sizeElements.push(input);
            this.#elms.inputs.appendChild(input);
        }
    }

    #setValue(value: number[] | undefined): void {
        const vl = value ?? [];
        if (vl.length < this.#inputs.length) {
            for (let i = vl.length; i < this.#inputs.length; i++) {
                this.#inputs[i]?.remove();
            }
        }
        if (vl.length > this.#inputs.length) {
            for (let i = this.#inputs.length; i < vl.length; i++) {
                this.#addItem();
            }
        }

        for (let i = 0; i < vl.length; i++) {
            this.#inputs[i]!.value = hex(vl[i]!);
        }
        this.#updateRange();
    }

    /**
     * 向列表中添加一个新项
     */
    #addItem(): void {
        const input = document.createElement("input");
        input.classList.add(styles.input, styles.number);
        input.type = "text";
        input.value = "00";
        input.maxLength = 3;

        input.addEventListener("focus", () => {
            input.select();
        });

        input.addEventListener("keyup", () => {
            this.#updateRange();
        });

        input.addEventListener("change", () => {
            console.log("change", input.value);
            const vl = parseInt(input.value, 16);
            if (!Number.isInteger(vl) || vl < 0 || vl > 0xff) {
                input.value = "00";
            } else {
                input.value = hex(vl);
            }
        });

        input.addEventListener("mouseover", (e) => {
            if (e.buttons === 2) {
                e.stopPropagation();
                e.preventDefault();
                e.stopImmediatePropagation();
                input.value = hex(Math.floor(Math.random() * 0xff));
            }
        });

        input.addEventListener("contextmenu", (e) => {
            e.stopPropagation();
            e.preventDefault();
            e.stopImmediatePropagation();
        });

        input.addEventListener("mousedown", (e) => {
            if (e.buttons === 2) {
                e.stopPropagation();
                e.preventDefault();
                e.stopImmediatePropagation();
                input.value = hex(Math.floor(Math.random() * 0xff));
            }
        });

        this.#inputs.push(input);
        this.#elms.inputs.appendChild(input);
        this.#updateRange();
    }

    /**
     * 从列表中移除最后一项
     */
    #removeItem(): void {
        const input = this.#inputs.pop();
        if (input === undefined) {
            return;
        }
        input.remove();
        this.#updateRange();
    }

    /**
     * 更新显示的字节范围信息
     * 格式：[begin - (begin+widthLength)) [(begin+widthLength) - (begin+total length)]
     * 第一部分表示长度字段，第二部分表示列表数据
     */
    #updateRange(): void {
        const sizeFormat = this.#sizeElements.length;
        const dataBegin = this.#begin + sizeFormat;
        const dataEnd = this.#begin + this.byteLength();

        const len = this.#inputs.length / this.#growStep;
        for (let i = 0; i < this.#sizeElements.length; i++) {
            const input = this.#sizeElements[i]!;
            input.readOnly = true;
            const value = len >> (i * 8);
            input.value = (value & 0xff).toString(16).padStart(2, "0");
            input.title = this.#inputs.length.toString();
        }

        this.#elms.range.textContent = `${this.#begin} - ${dataBegin} ) [ ${dataBegin} - ${dataEnd}`;
        this.dispatchEvent(new Event("change"));
    }
}

// 向浏览器注册自定义元素
define(ListRequestFieldElement);
